<template>
  <div class="p-l-d">
    <n-card>
      <div>
        <n-button
          style="margin-right: 5px"
          type="primary"
          dashed
          size="small"
          @click="openDialog"
        >
          <template #icon>
            <n-icon>
              <AddCircleOutline />
            </n-icon>
          </template>
          新增
        </n-button>
      </div>
      <br />
      <n-spin :show="loading">
        <n-data-table
          :columns="roleColumns"
          :data="roleData"
          :row-key="rowKey"
          default-expand-all
          style="margin-bottom: 10px; width: 100%"
          :max-height="tableHeight"
          :scroll-x="600"
          :row-props="rowProps"
        />
      </n-spin>
    </n-card>
    <n-card :title="'授权菜单（' + selectData.title + '）'">
      <div>
        <n-spin :show="treeLoading">
          <n-tree
            style="margin-top: 1em"
            block-line
            cascade
            :data="menuData"
            key-field="id"
            label-field="name"
            children-field="children"
            :default-expand-all="defaultExpand"
            :render-prefix="renderPrefix"
            checkable
            ref="myTreeRef"
            :checked-keys="roleMenuData.menuList"
            @update:checked-keys="selectChecked"
          />
        </n-spin>
      </div>
      <div style="display: flex; justify-content: flex-end; margin: 1rem">
        <n-button
          style="margin-right: 5px"
          type="primary"
          size="small"
          @click="checkAll"
          :loading="butLoading"
          :disabled="butLoading"
        >
          立即更新
        </n-button>
      </div>
    </n-card>

    <my-dialog
      :showModal="showModal"
      @closeModal="closeModal"
      @getRoleData="getRoleData"
      ref="myDialogRef"
    ></my-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, h, onMounted, inject } from "vue";
import { AddCircleOutline } from "@vicons/ionicons5";
import myDialog from "./dialog.vue";
import { getMenuList, getMenuTree } from "@/api/menu.ts";
import { searchMenuRequest } from "@/models/menuModel.ts";
import { NButton, NIcon, NImage, NPopconfirm, NPopover, NTag } from "naive-ui";
import { getRoleList } from "@/api/platform.ts";
import { getMenuIdsById, grantMenuToRole } from "@/api/permissions.ts";
import { allocationMenuRequest } from "@/models/permissionsModles.ts";

const selectData = ref({
  title: "",
  id: null,
});
const myTreeRef = ref(null);
const menuData = ref();
const roleData = ref([]);
const defaultExpand = ref(true);
const showModal = ref(false);
const tableHeight = ref(inject("tableHeight"));
const myDialogRef = ref<any>(null);
const queryInfo = ref<searchMenuRequest>({
  pageIndex: 1,
  pageSize: 10,
  menuName: null,
  menuType: null,
});
const menuTreeList = ref();
const butLoading = ref(false);
const loading = ref(false);
const treeLoading = ref(false);
const roleColumns = ref([
  {
    type: "selection",
    fixed: "left",
  },
  {
    title: "角色名称",
    key: "name",
    width: 150,
  },
  {
    title: "状态",
    key: "enable",
    render(row) {
      return h(
        NTag,
        {
          style: {
            marginRight: "6px",
          },
          type: row.enable ? "success" : "error",
          bordered: false,
        },
        {
          default: () => (row.enable ? "启用" : "禁用"),
        }
      );
    },
  },
  {
    title: "角色描述",
    key: "description",
    render(row) {
      return [
        h(
          NPopover,
          {
            trigger: "hover",
          },
          {
            trigger: () => {
              return h(
                NTag,
                {
                  style: {
                    marginRight: "6px",
                  },
                  type: "success",
                  bordered: false,
                },
                {
                  default: () => "描述",
                }
              );
            },
            default: () => {
              return row.description;
            },
          }
        ),
      ];
    },
  },
  {
    title: "操作",
    key: "actions",
    fixed: "right",
    render(row) {
      return [
        h(
          NPopconfirm,
          {
            positiveButtonProps: {
              size: "tiny",
            },
            negativeButtonProps: {
              size: "tiny",
            },
            onPositiveClick: (e) => {
              deleteDictionaryItem({ id: row.id }).then((res) => {
                if (res.code == 200) {
                  window.$message.success(res.message);

                  getDicItemList();
                } else {
                  window.$message.error(res.message);
                }
              });
            },
          },
          {
            trigger: () => {
              return h(
                NButton,
                {
                  style: { marginRight: "10px" },
                  strong: true,
                  secondary: true,
                  type: "error",
                  size: "small",
                },
                { default: () => "删除" }
              );
            },
            default: () => {
              return "确定要删除？";
            },
          }
        ),
        h(
          NButton,
          {
            strong: true,
            secondary: true,
            type: "warning",
            size: "small",
            onClick: () => openDicItemDialog(2, row.id),
          },
          { default: () => "编辑" }
        ),
      ];
    },
    width: 150,
  },
]);
const rowProps = (row) => {
  return {
    style: "cursor: pointer;",
    onClick: () => {
      selectData.value.title = row.name;
      selectData.value.id = row.id;
      roleMenuData.value.id = row.id;
      getRoleMenuDataById(row.id);
    },
  };
};
const roleMenuData = ref<allocationMenuRequest>({
  id: null,
  menuList: [],
});

onMounted(() => {
  getRoleData();
});
const getRoleData = () => {
  loading.value = true;
  treeLoading.value = true;
  getRoleList()
    .then((res) => {
      roleData.value = [];
      roleData.value = res.data;
      if (res.data.length > 0) {
        selectData.value.title = res.data[0].name;
        selectData.value.id = res.data[0].id;
        roleMenuData.value.id = res.data[0].id;
        getRoleMenuDataById(roleMenuData.value.id);
      }
      loading.value = false;
    })
    .catch((err) => {
      loading.value = false;
    });
  getMenuList(queryInfo.value)
    .then((res) => {
      menuData.value = [];
      menuData.value = res.data;
      getMenuTree().then((res) => {
        menuTreeList.value = res.data;
      });
      treeLoading.value = false;
    })
    .catch((err) => {
      treeLoading.value = false;
    });
};
const getRoleMenuDataById = (id) => {
  treeLoading.value = true;
  getMenuIdsById({ roleId: id })
    .then((res) => {
      roleMenuData.value.menuList = res.data;
      treeLoading.value = false;
    })
    .catch((err) => {
      treeLoading.value = false;
    });
};

const getMenuIcon = (url) => {
  // 这里可以是一个图标组件或者图片
  return h("img", {
    src: url,
    style: "width: 100%; height: auto;",
  });
};
const renderPrefix = (value) => {
  return h(NIcon, null, { default: () => h(getMenuIcon(value.option.icon)) });
};
const openDialog = () => {
  showModal.value = true;
  myDialogRef.value?.init();
};
const closeModal = () => {
  showModal.value = false;
};
const checkAll = () => {
  butLoading.value = true;
  roleMenuData.value.menuList = myTreeRef.value.getCheckedData().keys;

  grantMenuToRole(roleMenuData.value)
    .then((res) => {
      if (res.code == 200) {
        window.$message.success(res.message);
      } else {
        window.$message.error(res.message);
      }
      butLoading.value = false;
    })
    .catch((err) => {
      butLoading.value = false;
    });
};
const selectChecked = (keys: Array<string | number>, option: any, meta: any) => {
  roleMenuData.value.menuList = [];
  option.forEach((e) => {
    roleMenuData.value.menuList.push(e.id);
  });
};
</script>

<style lang="scss" scoped>
.p-l-d {
  display: grid;
  grid-template-columns: 45% calc(55% - 10px);
  gap: 10px;
  align-items: start;
}
</style>
